package com.ctshk.rpc.air.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.AirTouristType;
import com.ctshk.common.enums.NumberConstant;
import com.ctshk.common.model.TokenUser;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.rpc.air.dto.*;
import com.ctshk.rpc.air.entity.*;
import com.ctshk.rpc.air.mapper.*;
import com.ctshk.rpc.air.req.AirLowPriceByDateReq;
import com.ctshk.rpc.air.req.AirProductCostQueryReq;
import com.ctshk.rpc.air.req.AirProductSaleStrategyPriceReq;
import com.ctshk.rpc.air.service.IAirProductCostService;
import com.ctshk.rpc.air.service.IAirProductSaleStrategyService;
import com.ctshk.rpc.air.util.AirProductUtil;
import com.github.houbb.heaven.util.util.CollectionUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 机票产品成本表 服务实现类
 * </p>
 *
 * @author lihang
 * @since 2021-03-05
 */
@DubboService
public class AirProductCostServiceImpl extends ServiceImpl<AirProductCostMapper, AirProductCost> implements IAirProductCostService {

    @Autowired
    private AirProductCostMapper airProductCostMapper;


    @Autowired
    private AirProductCostDateMapper airProductCostDateMapper;


    @Autowired
    private AirProductCostTouristMapper airProductCostTouristMapper;


    @Autowired
    private AirFlightMapper airFlightMapper;

    @Autowired
    private AirProductMapper airProductMapper;

    @Autowired
    private IAirProductSaleStrategyService iAirProductSaleStrategyService;

    @Autowired
    private AirProductReservationSettingsMapper airProductReservationSettingsMapper;

    @Autowired
    private AirProductCostTaxationMapper airProductCostTaxationMapper;

    @Autowired
    private AirProductSaleRecordMapper airProductSaleRecordMapper;

    @Override
    public Result<List<AirProductPriceDateDTO>> queryAirLowPriceByDate(AirLowPriceByDateReq req, TokenUser tokenUser) {
        /**查詢所有的航班信息*/
        QueryWrapper<AirFlight> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(AirFlight::getArrCityId, req.getArrCityId());
        queryWrapper.lambda().eq(AirFlight::getDepCityId, req.getDepCityId());
        List<AirFlight> airFlightList = airFlightMapper.selectList(queryWrapper);
        /**查詢航班所有的機票產品信息*/
        Set<Long> airFlighIds = Sets.newHashSet();
        for (AirFlight airFlight : airFlightList) {
            airFlighIds.add(airFlight.getId());
        }
        QueryWrapper<AirProduct> productQueryWrapper = new QueryWrapper<>();
        productQueryWrapper.lambda().in(AirProduct::getRouteId, airFlighIds);
        List<AirProduct> airProductList = airProductMapper.selectList(productQueryWrapper);
        List<Long> ids = Lists.newArrayList();
        for (AirProduct airProduct : airProductList) {
            ids.add(airProduct.getId());
        }
        AirProductCostQueryReq airProductCostQueryReq = new AirProductCostQueryReq();
        airProductCostQueryReq.setProductIds(ids);
        airProductCostQueryReq.setStarDate(req.getStartDate());
        airProductCostQueryReq.setEndDate(req.getEndDate());
        airProductCostQueryReq.setRelationId(tokenUser.getId());
        List<AirProductPriceDTO> airProductPriceDTOList = queryProductCost(airProductCostQueryReq);
        Map<LocalDate, AirProductPriceDateDTO> priceMap = Maps.newHashMap();
        for (AirProductPriceDTO airProductPriceDTO : airProductPriceDTOList) {
            List<AirProductPriceTouristDTO> airProductPriceTouristDTOList = airProductPriceDTO.getAirProductPriceTouristDTOList();
            if (CollectionUtil.isEmpty(airProductPriceTouristDTOList)) {
                continue;
            }
            for (AirProductPriceTouristDTO airProductPriceTouristDTO : airProductPriceTouristDTOList) {
                List<AirProductPriceDateDTO> airProductPriceDateDTOList = airProductPriceTouristDTO.getAirProductPriceDateDTOList();
                for (AirProductPriceDateDTO airProductPriceDateDTO : airProductPriceDateDTOList) {
                    AirProductPriceDateDTO mapValue = priceMap.get(airProductPriceDateDTO.getDate());
                    if (null == mapValue) {
                        priceMap.put(airProductPriceDateDTO.getDate(), airProductPriceDateDTO);
                    } else {
                        BigDecimal price = airProductPriceDateDTO.getPrice();
                        BigDecimal lowPrice = mapValue.getPrice();
                        if (price.compareTo(lowPrice) < NumberConstant.ZERO.getValue().intValue()) {
                            priceMap.put(airProductPriceDateDTO.getDate(), airProductPriceDateDTO);
                        }
                    }
                }
            }
        }
        List<AirProductPriceDateDTO> airProductPriceDateDTOS = Lists.newArrayList();
        for (AirProductPriceDateDTO value : priceMap.values()) {
            airProductPriceDateDTOS.add(value);
        }
        return Result.success(airProductPriceDateDTOS);
    }


    @Override
    public List<AirProductPriceDTO> queryProductCost(AirProductCostQueryReq req) {
        /**查询所有的产品*/
        List<Long> productIds = req.getProductIds();
        QueryWrapper<AirProduct> airProductQueryWrapper = new QueryWrapper<>();
        airProductQueryWrapper.lambda().in(AirProduct::getId, productIds);
        List<AirProduct> airProductList = airProductMapper.selectList(airProductQueryWrapper);
        if (CollectionUtil.isEmpty(airProductList)) {
            return new ArrayList<>();
        }
        /**查詢所有的稅費*/
        QueryWrapper<AirProductCostTaxation> airProductCostTaxationQueryWrapper = new QueryWrapper<>();
        airProductCostTaxationQueryWrapper.lambda().in(AirProductCostTaxation::getProductId, productIds);
        List<AirProductCostTaxation> airProductCostTaxationList = airProductCostTaxationMapper.selectList(airProductCostTaxationQueryWrapper);
        //税费先按旅客类型分组
        Map<Long, List<AirProductCostTaxation>> touristTaxationMap = Maps.newHashMap();
        for (AirProductCostTaxation airProductCostTaxation : airProductCostTaxationList) {
            List<AirProductCostTaxation> mapValue = touristTaxationMap.get(airProductCostTaxation.getTouristId());
            if (null == mapValue) {
                mapValue = Lists.newArrayList();
            }
            mapValue.add(airProductCostTaxation);
            touristTaxationMap.put(airProductCostTaxation.getTouristId(), mapValue);
        }
        /**查询所有的成本*/
        QueryWrapper<AirProductCost> airProductCostQueryWrapper = new QueryWrapper<>();
        airProductCostQueryWrapper.lambda().in(AirProductCost::getAirProductId, productIds);
        List<AirProductCost> airProductCostList = airProductCostMapper.selectList(airProductCostQueryWrapper);
        Set<Long> airCostIdSet = Sets.newHashSet();
        for (AirProductCost airProductCost : airProductCostList) {
            airCostIdSet.add(airProductCost.getId());
        }
        /**查询所有的有效期*/
        QueryWrapper<AirProductCostDate> airProductCostDateQueryWrapper = new QueryWrapper<>();
        airProductCostDateQueryWrapper.lambda().in(AirProductCostDate::getCostId, airCostIdSet);
        List<AirProductCostDate> airProductCostDateList = airProductCostDateMapper.selectList(airProductCostDateQueryWrapper);
        /**查询所有的旅客成本*/
        QueryWrapper<AirProductCostTourist> airProductCostTouristQueryWrapper = new QueryWrapper<>();
        airProductCostTouristQueryWrapper.lambda().in(AirProductCostTourist::getCostId, airCostIdSet);
        if (CollectionUtil.isNotEmpty(req.getTouristTypeIds())) {
            airProductCostTouristQueryWrapper.lambda().in(AirProductCostTourist::getTouristTypeId, req.getTouristTypeIds());
        }
        /**查询预订信息 计算服务费和预订费*/
        QueryWrapper<AirProductReservationSettings> airProductReservationSettingsQueryWrapper = new QueryWrapper<>();
        airProductReservationSettingsQueryWrapper.lambda().in(AirProductReservationSettings::getAirProductId, productIds);
        List<AirProductReservationSettings> airProductReservationSettingsList = airProductReservationSettingsMapper.selectList(airProductReservationSettingsQueryWrapper);
        Map<Long, AirProductReservationSettings> airProductReservationSettingsMap = Maps.newHashMap();
        for (AirProductReservationSettings airProductReservationSettings : airProductReservationSettingsList) {
            airProductReservationSettingsMap.put(airProductReservationSettings.getAirProductId(), airProductReservationSettings);
        }

        List<AirProductCostTourist> airProductCostTouristList = airProductCostTouristMapper.selectList(airProductCostTouristQueryWrapper);
        if (CollectionUtils.isEmpty(airProductCostTouristList)) return Lists.newArrayList();
        /**开始组装*/
        /** step1 成本按照产品分组*/
        Map<Long, List<AirProductCost>> airProCostMap = Maps.newHashMap();
        for (AirProductCost airProductCost : airProductCostList) {
            List<AirProductCost> mapValue = airProCostMap.get(airProductCost.getAirProductId());
            if (null == mapValue) {
                mapValue = Lists.newArrayList();
            }
            mapValue.add(airProductCost);
            airProCostMap.put(airProductCost.getAirProductId(), mapValue);
        }
        /** step2 成本日期按照成本分组*/
        Map<Long, List<AirProductCostDate>> airCostDateMap = Maps.newHashMap();
        for (AirProductCostDate airProductCostDate : airProductCostDateList) {
            List<AirProductCostDate> mapValue = airCostDateMap.get(airProductCostDate.getCostId());
            if (null == mapValue) {
                mapValue = Lists.newArrayList();
            }
            mapValue.add(airProductCostDate);
            airCostDateMap.put(airProductCostDate.getCostId(), mapValue);
        }
        /** step3 成本旅客按照成本分组*/
        Map<Long, List<AirProductCostTourist>> airCostTourMap = Maps.newHashMap();
        for (AirProductCostTourist airProductCostTourist : airProductCostTouristList) {
            List<AirProductCostTourist> mapValue = airCostTourMap.get(airProductCostTourist.getCostId());
            if (null == mapValue) {
                mapValue = Lists.newArrayList();
            }
            mapValue.add(airProductCostTourist);
            airCostTourMap.put(airProductCostTourist.getCostId(), mapValue);
        }
        /**step4 获取需要返回的日期*/
        LocalDate starDate = req.getStarDate();
        LocalDate endDate = req.getEndDate().plusDays(1);
        List<LocalDate> priceDates = Stream.iterate(starDate, date -> date.plusDays(1))
                .limit(ChronoUnit.DAYS.between(starDate, endDate))
                .collect(Collectors.toList());
        /**stepp 5 按照产品进行组装*/
        List<AirProductPriceDTO> airProductPriceDTOList = Lists.newArrayList();
        for (AirProduct airProduct : airProductList) {
            AirProductReservationSettings airProductReservationSettings = airProductReservationSettingsMap.get(airProduct.getId());
            /**每个日期对应的成本id Map*/
            Map<LocalDate, Long> priceDateCostMap = Maps.newHashMap();
            AirProductPriceDTO airProductPriceDTO = new AirProductPriceDTO();
            airProductPriceDTO.setProductId(airProduct.getId());
            airProductPriceDTO.setProductCode(airProduct.getCode());
            List<AirProductCost> costValues = airProCostMap.get(airProduct.getId());
            if (CollectionUtil.isEmpty(costValues)) {
                continue;
            }
            Map<Long, AirProductCost> costMap = Maps.newHashMap();
            for (AirProductCost costValue : costValues) {
                costMap.put(costValue.getId(), costValue);
                //获取所有的有效期
                List<AirProductCostDate> costDateValues = airCostDateMap.get(costValue.getId());
                if (CollectionUtil.isEmpty(costDateValues)) {
                    continue;
                }
                Set<LocalDate> localDateSet = Sets.newHashSet();
                for (AirProductCostDate costDateValue : costDateValues) {
                    LocalDate dateBegin = costDateValue.getDateBegin();
                    LocalDate dateEnd = costDateValue.getDateEnd();
                    List<LocalDate> costDateBt = Stream.iterate(dateBegin, date -> date.plusDays(1))
                            .limit(ChronoUnit.DAYS.between(dateBegin, dateEnd))
                            .collect(Collectors.toList());
                    localDateSet.addAll(costDateBt);
                }
                for (LocalDate priceDate : priceDates) {
                    if (localDateSet.contains(priceDate)) {
                        priceDateCostMap.put(priceDate, costValue.getId());
                    }
                }
            }
            /**不传旅客类型 则返回所有旅客类型*/
            List<Long> typeIds = req.getTouristTypeIds();
            if (CollectionUtil.isEmpty(typeIds)) {
                typeIds = Lists.newArrayList();
                for (AirTouristType value : AirTouristType.values()) {
                    typeIds.add(value.getType().longValue());
                }
            }
            List<AirProductPriceTouristDTO> airProductPriceTouristDTOList = Lists.newArrayList();
            for (Long typeId : typeIds) {
                AirProductPriceTouristDTO airProductPriceTouristDTO = new AirProductPriceTouristDTO();
                airProductPriceTouristDTO.setAirTouristTypeId(typeId.intValue());
                airProductPriceTouristDTO.setAirTouristTypeName(AirTouristType.get(typeId.intValue()).getName());
                List<AirProductPriceDateDTO> airProductPriceDateDTOList = Lists.newArrayList();
                for (Map.Entry<LocalDate, Long> entry : priceDateCostMap.entrySet()) {
                    List<AirProductCostTourist> costTourists = airCostTourMap.get(entry.getValue());
                    AirProductCost productCost = costMap.get(entry.getValue());
                    Map<Long, AirProductCostTourist> map = Maps.newHashMap();
                    if (CollectionUtil.isNotEmpty(costTourists)) {
                        for (AirProductCostTourist costTourist : costTourists) {
                            map.put(costTourist.getTouristTypeId(), costTourist);
                        }
                    }
                    if (map.containsKey(typeId)) {
                        AirProductCostTourist tourist = map.get(typeId);
                        AirProductPriceDateDTO airProductPriceDateDTO = new AirProductPriceDateDTO();
                        airProductPriceDateDTO.setDate(entry.getKey());
                        airProductPriceDateDTO.setWeek(entry.getKey().getDayOfWeek().getValue());
                        List<AirProductCostTaxation> airProductCostTaxations = touristTaxationMap.get(tourist.getId());
                        List<AirProductCostTaxationDTO> airProductCostTaxationDTOList = EntityUtil.copyList(airProductCostTaxations, AirProductCostTaxationDTO.class);
                        airProductPriceDateDTO.setAirProductCostTaxationDTOList(airProductCostTaxationDTOList);
                        airProductPriceDateDTO.setCurrencyId(productCost.getCurrencyId());
                        airProductPriceDateDTO.setCurrencyName(productCost.getCurrencyName());
                        BigDecimal price = tourist.getCostPrice();
                        /**计算预订信息中的预订服务费*/
                        Integer serviceChargeType = airProductReservationSettings.getServiceChargeType();
                        BigDecimal serviceChargePrice = airProductReservationSettings.getServiceChargePrice();
                        if (serviceChargeType.intValue() == 1) {
                            serviceChargePrice = airProductReservationSettings.getServiceChargePrice();
                        } else {
                            serviceChargePrice = price.multiply(airProductReservationSettings.getServiceChargePrice().divide(new BigDecimal(100)));
                        }
                        price.add(serviceChargePrice);
                        airProductPriceDateDTO.setServiceChargePrice(serviceChargePrice);
                        airProductPriceDateDTO.setPrice(price);
                        airProductPriceDateDTO.setDailyStock(productCost.getDailyStock());
                        airProductPriceDateDTO.setCurrencyId(productCost.getCurrencyId());
                        airProductPriceDateDTO.setCurrencyName(productCost.getCurrencyName());
                        airProductPriceDateDTOList.add(airProductPriceDateDTO);
                    }
                }
                airProductPriceTouristDTO.setAirProductPriceDateDTOList(airProductPriceDateDTOList);
                airProductPriceTouristDTOList.add(airProductPriceTouristDTO);
            }
            airProductPriceDTO.setAirProductPriceTouristDTOList(airProductPriceTouristDTOList);
            AirProductPriceSettingsDTO airProductPriceSettingsDTO = EntityUtil.copy(airProductReservationSettings, AirProductPriceSettingsDTO.class);
            airProductPriceDTO.setAirProductPriceSettingsDTO(airProductPriceSettingsDTO);
            airProductPriceDTOList.add(airProductPriceDTO);
        }
        if (req.getIsMark()) {//需要计算上架策略
            AirProductSaleStrategyPriceReq airProductSaleStrategyPriceReq = new AirProductSaleStrategyPriceReq();
            airProductSaleStrategyPriceReq.setChannelType(req.getChannelType());
            airProductSaleStrategyPriceReq.setRelationId(req.getRelationId());
            airProductSaleStrategyPriceReq.setStarDate(req.getStarDate());
            airProductSaleStrategyPriceReq.setEndDate(req.getEndDate());
            airProductSaleStrategyPriceReq.setProductIds(req.getProductIds());
            List<AirProductSaleStrategyPriceDTO> airProductSaleStrategyPriceDTOList = iAirProductSaleStrategyService.queryProductStrategy(airProductSaleStrategyPriceReq);
            QueryWrapper<AirProductSaleRecord> productSaleRecordQueryWrapper = new QueryWrapper<>();
            productSaleRecordQueryWrapper.lambda().in(AirProductSaleRecord::getProductId, req.getProductIds());
            productSaleRecordQueryWrapper.lambda().ge(AirProductSaleRecord::getSalesDate, req.getStarDate());
            productSaleRecordQueryWrapper.lambda().lt(AirProductSaleRecord::getSalesDate, req.getEndDate());
            List<AirProductSaleRecord> airProductSaleRecordList = airProductSaleRecordMapper.selectList(productSaleRecordQueryWrapper);
            Map<String, Integer> airProductSaleRecordMap = Maps.newHashMap();
            for (AirProductSaleRecord airProductSaleRecord : airProductSaleRecordList) {
                String key = AirProductUtil.getSaleRecodeMapKey(airProductSaleRecord.getChannel(), airProductSaleRecord.getSalesDate(), airProductSaleRecord.getCustomId(),
                        airProductSaleRecord.getProductId());
                Integer number = airProductSaleRecordMap.get(key);
                if (null == number) {
                    airProductSaleRecordMap.put(key, airProductSaleRecord.getSoldNumber());
                } else {
                    airProductSaleRecordMap.put(key, airProductSaleRecord.getSoldNumber() + number);
                }

            }
            return AirProductUtil.assmleProductStrategy(airProductPriceDTOList, airProductSaleStrategyPriceDTOList, airProductSaleRecordMap, req.getChannelType(),
                    req.getRelationId());
        } else {
            return airProductPriceDTOList;
        }

    }

    @Override
    public Integer getDailyStock(Long productId, LocalDate date) {
        AirProductCost currentlyValidCost = airProductCostMapper.getCurrentlyValidCost(productId, date);
        return currentlyValidCost != null ? Optional.ofNullable(currentlyValidCost.getDailyStock()).orElse(0) : 0;
    }
}
